Skip to content

Conversation

@Stubbjax
Copy link

Fixes #24 from the patch repository

This change fixes inconsistent mine collision detection by replacing the partition manager's circle fill algorithm with a more precise algorithm. The new logic is placed behind a new RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM preprocessor directive to help isolate the change as it is potentially slightly less performant.

The retail circle fill logic - an implementation of the midpoint circle algorithm - does not accurately cover the cells occupied by spherical or cylindrical geometry. This leads to various collision inaccuracies throughout the game, one of which is the infamous mine behaviour described in #24. Various collision logic is only processed within partition cells that are considered occupied - the partition cells act as a 'broad phase' to determine which geometry then needs to be checked for overlaps.

It's particularly important to note that objects with a geometry radius >= 20 and < 40 (the most common range) only cover a single partition cell, for example Tunnel Networks (radius: 25) and Stinger Sites (radius: 30). This can be seen in the video below. A blue/green square indicates an occupied cell.

SINGLE_CELL.mp4

Mines happen to fit right within this range with a radius of 30, and therefore only end up covering a single cell. This is a problem as most units happen to be smaller than a single partition cell, and can end up bypassing adjacent occupied cells altogether. Below is an example of this happening.

DODGER.mp4

Below is a demonstration of the difference in cell coverage in retail (left, blue) vs this change (right, yellow) at different radii. It should be apparent that retail cell coverage becomes more inaccurate as geometry radii increases towards each multiple of the partition cell size (40, 80, 120, etc.), whereas the new algorithm is always perfectly accurate. Note that radii < 20 uses a separate dedicated 'small geometry' algorithm which is 100% accurate.

GRID_COMP.mp4

And below is a direct comparison between retail mine cell coverage and the new mine cell coverage.

Before

Mine cell coverage using the retail algorithm

image

After

Mine cell coverage using the new algorithm

image

And some real gameplay demonstrations for good measure.

Before

The Technical skips over several mines, allowing the terrorists to destroy the War Factory

BAD_MINES.mp4

After

The Technical and terrorists explode on the mines as expected

GOOD_MINES.mp4

@Stubbjax Stubbjax self-assigned this Jan 28, 2026
@Stubbjax Stubbjax added Bug Something is not working right, typically is user facing Major Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Gen Relates to Generals ZH Relates to Zero Hour NoRetail This fix or change is not applicable with Retail game compatibility labels Jan 28, 2026
@greptile-apps
Copy link

greptile-apps bot commented Jan 28, 2026

Greptile Overview

Greptile Summary

This PR replaces the partition manager's midpoint circle algorithm with a precise circle-to-AABB collision test to fix inconsistent mine collision behavior. The change addresses a critical gameplay issue where objects with geometry radii between 20 and 40 (including mines with radius 30) only occupied a single partition cell, allowing units to bypass them entirely.

Key Changes:

  • Added RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM preprocessor define to control algorithm selection
  • Implemented doCircleFillPrecise() method using accurate circle-to-cell overlap detection
  • Applied changes identically to both Generals and GeneralsMD codebases
  • Preserved retail behavior via conditional compilation guards

Algorithm Details:
The new doesCircleOverlapCell() function finds the closest point on the cell's bounding box to the circle center and checks if that distance is within the radius. This guarantees 100% accurate cell coverage for all geometry radii, particularly fixing the critical 20-40 range where the midpoint circle algorithm was most inaccurate.

Validation:
The PR includes extensive visual demonstrations showing improved cell coverage and gameplay videos confirming mines now properly detect passing units.

Confidence Score: 5/5

  • This PR is safe to merge with very high confidence
  • The implementation is mathematically sound, uses a well-established collision detection algorithm, preserves retail compatibility through conditional compilation, has been thoroughly demonstrated with visual evidence and gameplay testing, and applies changes consistently across both codebases
  • No files require special attention

Important Files Changed

Filename Overview
Core/GameEngine/Include/Common/GameDefines.h Added RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM preprocessor define to control circle fill algorithm selection
Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp Implemented precise circle fill algorithm using circle-to-AABB collision test and added conditional compilation to preserve retail behavior
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp Implemented precise circle fill algorithm using circle-to-AABB collision test and added conditional compilation to preserve retail behavior (Zero Hour version)

Sequence Diagram

sequenceDiagram
    participant PD as PartitionData
    participant PM as PartitionManager
    participant Cell as PartitionCell
    
    Note over PD: updateCellsTouched() called
    
    alt Geometry is SPHERE or CYLINDER
        alt RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM = 1
            PD->>PD: doCircleFill(x, y, radius)
            Note over PD: Uses midpoint circle algorithm<br/>(less accurate)
        else RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM = 0
            PD->>PD: doCircleFillPrecise(x, y, radius)
            Note over PD: Calculate bounding cells
            PD->>PM: worldToCell(centerX ± radius, centerY ± radius)
            PM-->>PD: minCellX, minCellY, maxCellX, maxCellY
            PD->>PM: getCellSize()
            PM-->>PD: cellSize
            
            loop For each cell (x, y) in bounding box
                PD->>PD: doesCircleOverlapCell(centerX, centerY, radius, cellX, cellY, cellSize)
                Note over PD: Find closest point on cell to circle<br/>Check if distance < radius
                
                alt Circle overlaps cell
                    PD->>PM: getCellAt(x, y)
                    PM-->>PD: cell
                    alt cell exists
                        PD->>Cell: addSubPixToCoverage(cell)
                    end
                end
            end
        end
    end
    
    Note over PD: Partition cells now accurately<br/>reflect object's collision bounds
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +2122 to +2123
// TheSuperHackers @bugfix Stubbjax 29/01/2026 Use precise circle fill to improve
// collision accuracy, most notably for objects with geometry radii >= 20 and < 40.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

date in comment shows 29/01/2026 but PR was created on 2026-01-28

Prompt To Fix With AI
This is a comment left during a code review.
Path: Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp
Line: 2122:2123

Comment:
date in comment shows 29/01/2026 but PR was created on 2026-01-28

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +2126 to +2127
// TheSuperHackers @bugfix Stubbjax 29/01/2026 Use precise circle fill to improve
// collision accuracy, most notably for objects with geometry radii >= 20 and < 40.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

date in comment shows 29/01/2026 but PR was created on 2026-01-28

Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp
Line: 2126:2127

Comment:
date in comment shows 29/01/2026 but PR was created on 2026-01-28

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is not working right, typically is user facing Gen Relates to Generals Major Severity: Minor < Major < Critical < Blocker NoRetail This fix or change is not applicable with Retail game compatibility Performance Is a performance concern ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate China mines issues, where units can drive or walk through or over mines without taking damage

1 participant